#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include "parse.h"
#include <sys/types.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>

#define FILE_MAX_SIZE (1024*1024)
#define ECHO_PORT 9999
#define BUF_SIZE 4096

char res[4096];
int record[100][2];

int fds[128];
const int len = 128;

int close_socket(int sock);
void strcopy(char *dest, char *src, int head, int tail);
void get_local_time(char*, int);
long get_file_size(char* filename);
void write_log_file(char*,long,char*,int, int);

enum{
    ERR, ACC
};


int main(int argc, char *argv[])
{
    int sock, client_sock;
    ssize_t readret;
    socklen_t cli_size;
    struct sockaddr_in addr, cli_addr;
    char buf[BUF_SIZE];
    fprintf(stdout, "----- Echo Server -----\n");

    /* all networked programs must create a socket */
    if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        fprintf(stderr, "Failed creating socket.\n");
        return EXIT_FAILURE;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(ECHO_PORT);
    addr.sin_addr.s_addr = INADDR_ANY;

    /* servers bind sockets to ports---notify the OS they accept connections */
    if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
    {
        close_socket(sock);
        fprintf(stderr, "Failed binding socket.\n");
        return EXIT_FAILURE;
    }


    if (listen(sock, 5))
    {
        close_socket(sock);
        fprintf(stderr, "Error listening on socket.\n");
        return EXIT_FAILURE;
    }

    /* finally, loop waiting for input and then write it back */
    while (1)
    {
        cli_size = sizeof(cli_addr);
        if ((client_sock = accept(sock, (struct sockaddr *)&cli_addr,
                                  &cli_size)) == -1)
        {
            close(sock);
            fprintf(stderr, "Error accepting connection.\n");
            return EXIT_FAILURE;
        }

        readret = 0;
        int mark;

        while ((readret = recv(client_sock, buf, BUF_SIZE, 0)) >= 1)
        {
            char *str;
            int last = 0;
            str = strstr(buf, "\r\n\r\n");
            int i = 0;

            while (str != NULL)
            {
                str += 4;
                record[i][0] = last, record[i][1] = str - buf;
                strcopy(res, buf, record[i][0], record[i][1]);

                Request *request = parse(res, readret, sock);

                if( request == NULL){
                    //char req[30] = "HTTP/1.1 400 Bad request\r\n\r\n";
                    strcpy(res, "HTTP/1.1 400 Bad request\r\n\r\n");
                } 
                else if( strcmp(request->http_version, "HTTP/1.1") ){
                    strcpy(res, "HTTP/1.1 505 HTTP Version not supported\r\n\r\n");
                }
                else if(strcmp(request->http_method,"GET") == 0 || strcmp(request->http_method,"HEAD") == 0){
                    char path[50];
                    
                    strcpy(path, request->http_uri);
                    strcat(path, "index.html");
                    char a[50]="static_site";
                    strcat(a,path);
                    
                    int fd_in = open(a, O_RDONLY);
                    if(fd_in == -1){
                        strcpy(res,"HTTP/1.1 404 Not Found\r\n\r\n");
                    }
                    else{
                        int index;
                        strcpy(res,"HTTP/1.1 200 OK\r\n");

                        //client and server 之间的连接方式，请求头connect
                        for(index = 0;index < request->header_count ; index++){
                            if(strcmp(request->headers[index].header_name, "Connection") == 0){
                                strcat(res, "Connection: ");
                                strcat(res, request->headers[index].header_value);
                            }
                        }

                        //通信时间
                        strcat(res, "\nDate: ");

                        time_t rawtime;
                        struct tm *info;
                        char buffer[35];
                        
                        time( &rawtime );
                        
                        info = localtime( &rawtime );
                        
                        strftime(buffer, 80, "%a, %d %b %Y %H:%M:%S GMT\n", info);
                        strcat(res, buffer);
                        
                        if(strcmp(request->http_method,"GET") == 0){
                            char fbuf[BUF_SIZE];

                            int content_len = read(fd_in,fbuf,BUF_SIZE);
                            char len[5];
                            memset(len, 0, sizeof(len));
                            sprintf(len, "%d", content_len);
                            strcat(res, "Content-Length: ");
                            strcat(res, len);
                            strcat(res, "\n\n");

                            strcat(res,fbuf);
                            //ShellExecute(0, "open", "./static_site/index.html",0, 0, 1);
                        }
                    }
                }
                else if(strcmp(request->http_method,"POST") == 0 ){;}
                else{
                    strcpy(res, "HTTP/1.1 501 Not Implemented\r\n\r\n");
                }


                last = str - buf;
                str = strstr(str, "\r\n\r\n");
                i++;

                
                if (send(client_sock, res, BUF_SIZE, 0) <=0)
                {
                    close_socket(client_sock);
                    close_socket(sock);
                    fprintf(stderr, "Error sending to client.\n");
                    return EXIT_FAILURE;
                }
                memset(res, 0, BUF_SIZE);
            }
            memset(buf, 0, BUF_SIZE);
        }

        if (readret == -1)
        {
            close_socket(client_sock);
            close_socket(sock);
            fprintf(stderr, "Error reading from client socket.\n");
            return EXIT_FAILURE;
        }

        if (close_socket(client_sock))
        {
            close_socket(sock);
            fprintf(stderr, "Error closing client socket.\n");
            return EXIT_FAILURE;
        }
    }

    close_socket(sock);

    return EXIT_SUCCESS;
}

int close_socket(int sock)
{
    if (close(sock))
    {
        fprintf(stderr, "Failed closing socket.\n");
        return 1;
    }
    return 0;
}

void strcopy(char *dest, char *src, int head, int tail)
{
    for (int i = head; i < tail; i++)
    {
        dest[i - head] = src[i];
    }
}

